package com.anpy.security.security;

import com.anpy.security.entity.Platform;
import com.anpy.security.entity.User;
import com.anpy.security.repository.PlatformRepository;
import com.anpy.security.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private PlatformRepository platformRepository;

    @Override
    @Transactional
    public UserDetails loadUserByUsername(String usernameWithPlatform) throws UsernameNotFoundException {
        // Username format: username@platformCode
        String[] parts = usernameWithPlatform.split("@");
        if (parts.length != 2) {
            throw new UsernameNotFoundException("Invalid username format. Expected: username@platformCode");
        }
        
        String username = parts[0];
        String platformCode = parts[1];
        
        Platform platform = platformRepository.findByCode(platformCode)
                .orElseThrow(() -> new UsernameNotFoundException("Platform not found: " + platformCode));
        
        User user = userRepository.findByUsernameAndPlatform(username, platform)
                .orElseThrow(() -> new UsernameNotFoundException("User not found: " + username + " in platform: " + platformCode));
        
        return new org.springframework.security.core.userdetails.User(
                usernameWithPlatform,
                user.getPassword(),
                user.isEnabled(),
                true,
                true,
                true,
                getAuthorities(user, platform)
        );
    }
    
    private Collection<? extends GrantedAuthority> getAuthorities(User user, Platform platform) {
        // Combine role and permission authorities with platform prefix
        // Format: ROLE_[platformCode]_[roleName] and [platformCode]_[permissionName]
        String platformPrefix = platform.getCode() + "_";
        
        // Add role-based authorities
        Collection<GrantedAuthority> authorities = user.getRoles().stream()
                .map(role -> new SimpleGrantedAuthority("ROLE_" + platformPrefix + role.getName()))
                .collect(Collectors.toList());
        
        // Add permission-based authorities
        user.getRoles().forEach(role -> {
            role.getPermissions().forEach(permission -> {
                authorities.add(new SimpleGrantedAuthority(platformPrefix + permission.getName()));
            });
        });
        
        return authorities;
    }
}
